package com.ruoyi.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.Diagnose;
import com.ruoyi.system.domain.PatientCaseInfo;
import com.ruoyi.system.domain.Surgery;
import com.ruoyi.system.domain.vo.PatientCaseReqVO;
import com.ruoyi.system.domain.vo.PatientCaseRespVO;
import com.ruoyi.system.mapper.PatientCaseInfoMapper;
import com.ruoyi.system.service.IDiagnoseService;
import com.ruoyi.system.service.IPatientCaseInfoService;
import com.ruoyi.system.service.ISurgeryService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.ruoyi.common.utils.SecurityUtils.getUserId;
import static com.ruoyi.common.utils.SecurityUtils.getUsername;

/**
 * 病案信息Service业务层处理
 *
 * @author ruoyi
 * @date 2024-07-25
 */
@Service
public class PatientCaseInfoServiceImpl implements IPatientCaseInfoService {
    private static final Logger log = LoggerFactory.getLogger(PatientCaseInfoServiceImpl.class);
    @Resource
    private PatientCaseInfoMapper patientCaseInfoMapper;

    @Autowired
    public StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ISurgeryService surgeryService;

    @Autowired
    private IDiagnoseService diagnoseService;

    /**
     * 查询病案信息
     *
     * @param id 病案信息主键
     * @return 病案信息
     */
    @Override
    public PatientCaseInfo selectPatientCaseInfoById(Long id) {
        return patientCaseInfoMapper.selectPatientCaseInfoById(id);
    }

    /**
     * 查询病案信息列表
     *
     * @param caseReqVO 病案信息
     * @return 病案信息
     */
    @Override
    public List<PatientCaseInfo> selectPatientCaseInfoList(PatientCaseReqVO caseReqVO) {
        if (caseReqVO.getChuyuanriqi() != null && caseReqVO.getChuyuanriqi().length > 1) {
            caseReqVO.setCybeginTime(caseReqVO.getChuyuanriqi()[0]);
            caseReqVO.setCyendTime(caseReqVO.getChuyuanriqi()[1]);
        }
        if (caseReqVO.getRuyuanriqi() != null && caseReqVO.getRuyuanriqi().length > 1) {
            caseReqVO.setRybeginTime(caseReqVO.getRuyuanriqi()[0]);
            caseReqVO.setRyendTime(caseReqVO.getRuyuanriqi()[1]);
        }
        if (caseReqVO.getCreateDate() != null && caseReqVO.getCreateDate().length > 1) {
            caseReqVO.setCreateBeginTime(caseReqVO.getCreateDate()[0]);
            caseReqVO.setCreateEndTime(caseReqVO.getCreateDate()[1]);
        }

        return patientCaseInfoMapper.selectPatientCaseInfoList(caseReqVO);
    }


    /**
     * 新增病案信息
     *
     * @param patientCaseInfo 病案信息
     * @return 结果
     */
    @Override
    public int insertPatientCaseInfo(PatientCaseInfo patientCaseInfo) {

        //检验住院号是否存在
        this.checkZYH(patientCaseInfo);

        List<PatientCaseInfo> list = CollUtil.newArrayList(patientCaseInfo);
        this.buildData(list, true);
        return patientCaseInfoMapper.insertPatientCaseInfo(list.get(0));
    }

    private void checkZYH(PatientCaseInfo patientCaseInfo) {
        //检验住院号是否存在
        PatientCaseInfo patientCase = patientCaseInfoMapper.selectByzhuyuanhaos(patientCaseInfo);
        if (patientCase != null) {
            throw new ServiceException("住院号重复：" + patientCase.getZhuyuanhao() + "已经存在病案信息管理系统！");
        }
    }

    /**
     * 修改病案信息
     *
     * @param patientCaseInfo 病案信息
     * @return 结果
     */
    @Override
    public int updatePatientCaseInfo(PatientCaseInfo patientCaseInfo) {
        PatientCaseInfo patientCase = patientCaseInfoMapper.selectPatientCaseInfoById(patientCaseInfo.getId());
        if (patientCase == null) {
            throw new ServiceException("病案信息不存在!");
        }
        // 已审核数据 只要超级管理员可修复
        if (patientCase.getAuditStatus() == 1 && isAdmin()) {
            throw new ServiceException("病案信息已审核，不能修改!");
        }

        //检验住院号是否存在
        this.checkZYH(patientCaseInfo);


        List<PatientCaseInfo> list = CollUtil.newArrayList(patientCaseInfo);
        this.buildData(list, false);
        return patientCaseInfoMapper.updatePatientCaseInfo(list.get(0));
    }

    @Transactional(rollbackFor = Exception.class)
    public void buildData(List<PatientCaseInfo> list, Boolean flag) {

        List<String> idCards = list.stream().map(PatientCaseInfo::getShenfenzhenghao).filter(StrUtil::isNotBlank).collect(Collectors.toList());
        //清空病案号  自动生成
        list.forEach(item -> {
            item.setBinganhao("");
        });

        List<PatientCaseRespVO> idCardList = new ArrayList<>();
        if (CollUtil.isNotEmpty(idCards)) {
            List<PatientCaseRespVO> resultList = patientCaseInfoMapper.selectByIdCards(idCards);
            if (CollUtil.isNotEmpty(resultList)) {
                idCardList = resultList;
            }
        }

        List<PatientCaseRespVO> finalIdCardList = idCardList;
        String username = getUsername();
        list.forEach(item -> {

            //存在身份证
            if (StrUtil.isNotBlank(item.getShenfenzhenghao())) {
                //去数据库匹对  存在取数据库   数据库查询不到   查询当前的数据  存在取当前相同身份证的病案号 不存在就用默认的
                PatientCaseRespVO respVO = finalIdCardList.stream().filter(idCard -> Objects.equals(idCard.getShenfenzhenghao(), item.getShenfenzhenghao())).findFirst().orElse(null);
                if (respVO != null) {
                    //数据库存在
                    item.setBinganhao(respVO.getBinganhao());
                } else {
                    //不存在从当前的找
                    PatientCaseInfo patientCase = list.stream().filter(res -> Objects.equals(res.getShenfenzhenghao(), item.getShenfenzhenghao())).findFirst().orElse(null);
                    if (patientCase != null && StrUtil.isNotBlank(patientCase.getBinganhao())) {
                        //当前存在
                        item.setBinganhao(patientCase.getBinganhao());
                    } else {
                        //默认生成一个病案号
                        item.setBinganhao(idUtil());
                    }
                }
            } else {
                //默认生成一个病案号
                item.setBinganhao(idUtil());
            }
            Date nowDate = DateUtils.getNowDate();
            if (flag) {
                item.setCreateTime(nowDate);
                item.setCreateBy(username);
            }
            item.setUpdateTime(nowDate);
            item.setUpdateBy(username);
        });
    }

    /*@Override
    public String idUtil() {
        //时间戳 后面拼接流水号 如果需要  可以加上时分秒
        String datetime = new SimpleDateFormat("yyMM").format(new Date());
        //这里是 Redis key的前缀，如: 表名:日期  如果不需要去掉表名也可以
        String key = MessageFormat.format("{0}:{1}", "patient_case", datetime);
        //查询 key 是否存在， 不存在返回 1 ，存在的话则自增加1
        Long redisId = stringRedisTemplate.opsForValue().increment(key, 1);
        if (redisId == null) {
            return IdUtil.getSnowflake(1, 16).nextIdStr();
        }
        if (redisId == 1) {

            LocalDateTime startTime = LocalDateTime.now();
            LocalDateTime endTime = getLocalDateTimeMax(LocalDate.now());
            Long second = GetDateUtils.getSecond(startTime, endTime);

            // 设置key过期时间, 保证每天的流水号从1开始
            stringRedisTemplate.expire(key, second, TimeUnit.SECONDS);
        }
        //这里是 5 位id，如果位数不够可以自行修改 ，下面的意思是 得到上面 key 的 值，位数为4 ，不够的话在左边补 0 ，比如  110 会变成  000110
        String value = StringUtils.leftPad(String.valueOf(redisId), 5, "0");
        //然后把 时间戳和优化后的 ID 拼接
        return MessageFormat.format("{0}{1}", datetime, value);
    }*/
    @Override
    public String idUtil() {
        //查询 key 是否存在， 不存在返回 1 ，存在的话则自增加1
        Long redisId = stringRedisTemplate.opsForValue().increment("patient_case_id", 1);
        if (redisId == null) {
            throw new ServiceException("系统异常,请联系开发者!");
        }
        //这里是 5 位id，如果位数不够可以自行修改 ，下面的意思是 得到上面 key 的 值，位数为4 ，不够的话在左边补 0 ，比如  110 会变成  000110

        return "450321" + StringUtils.leftPad(String.valueOf(redisId), 6, "0");
    }

    public LocalDateTime getLocalDateTimeMax(LocalDate localDate) {
        return LocalDateTime.of(localDate, LocalTime.MAX);
    }

    /**
     * 批量删除病案信息
     *
     * @param ids 需要删除的病案信息主键
     * @return 结果
     */
    @Override
    public int deletePatientCaseInfoByIds(Long[] ids) {
        if (CollUtil.isEmpty(Arrays.asList(ids))) {
            return 0;
        }
        List<PatientCaseInfo> patientCaseList = patientCaseInfoMapper.listByIds(ids);
        if (CollUtil.isEmpty(patientCaseList)) {
            throw new ServiceException("病案信息不存在!");
        }

        Long userId = getUserId();
        List<String> indexList = new ArrayList<>();


        for (PatientCaseInfo patientCase : patientCaseList) {
            // 已审核数据 只要超级管理员可删除
            if (patientCase.getAuditStatus() == 1) {
                //throw new ServiceException("病案信息已审核，不能修改!");
                indexList.add(patientCase.getBinganhao());
            }
        }

        if (CollUtil.isNotEmpty(indexList) && isAdmin()) {
            String message = StrUtil.join("，", indexList);
            throw new ServiceException("病案号：" + message + " 已审核，不能删除");
        }


        return patientCaseInfoMapper.deletePatientCaseInfoByIds(ids);
    }

    /**
     * 判断当前登录人是不是超级管理员
     *
     * @return
     */
    public boolean isAdmin() {
        return getUserId() != 1L;
    }

    /**
     * 删除病案信息信息
     *
     * @param id 病案信息主键
     * @return 结果
     */
    @Override
    public int deletePatientCaseInfoById(Long id) {
        return patientCaseInfoMapper.deletePatientCaseInfoById(id);
    }

    /**
     * 最大导入数量
     */
    private final static Integer IMPORT_NUM = 5000;

    @Override
    public String importCase(List<PatientCaseInfo> patientCaseList, boolean updateSupport, String operName) {
        if (CollUtil.isEmpty(patientCaseList)) {
            throw new ServiceException("导入数据不能为空！");
        }
        if (patientCaseList.size() > IMPORT_NUM) {
            throw new ServiceException("最大支持导入" + IMPORT_NUM + "条数据");
        }

        List<String> diagnoseNameList = new ArrayList<>();
        List<String> surgeryNameList = new ArrayList<>();

        //住院号 患者姓名不能为空
        AtomicInteger index = new AtomicInteger(2);
        patientCaseList.forEach(item -> {
            if (StrUtil.isBlank(item.getZhuyuanhao())) {
                throw new ServiceException("第" + index.get() + "行的住院号不能为空！");
            }
            if (StrUtil.isBlank(item.getBingrenxingming())) {
                throw new ServiceException("第" + index.get() + "行的病人姓名不能为空！");
            }

            if (StrUtil.isNotBlank(item.getShoushucaozuomingcheng())) {
                surgeryNameList.add(item.getShoushucaozuomingcheng());
            }

            addName(diagnoseNameList, item.getRuyuanzhenduan());
            addName(diagnoseNameList, item.getChuyuanzhuzhenduan());
            addName(diagnoseNameList, item.getCizhenduan1());
            addName(diagnoseNameList, item.getCizhenduan2());
            addName(diagnoseNameList, item.getCizhenduan3());
            addName(diagnoseNameList, item.getCizhenduan4());
            addName(diagnoseNameList, item.getCizhenduan5());
            addName(diagnoseNameList, item.getCizhenduan6());
            addName(diagnoseNameList, item.getCizhenduan7());
            addName(diagnoseNameList, item.getCizhenduan8());
            addName(diagnoseNameList, item.getCizhenduan9());
            addName(diagnoseNameList, item.getCizhenduan10());


            index.getAndIncrement();
        });


        //判断住院号是否重复
        Map<String, Long> zhuyuanhaoMapGroup = patientCaseList.stream().collect(Collectors.groupingBy(PatientCaseInfo::getZhuyuanhao, Collectors.counting()));
        List<String> names = zhuyuanhaoMapGroup.entrySet().stream().filter(entry -> entry.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(names)) {
            throw new ServiceException("导入的Excel住院号重复：" + String.join("，", names));
        }

        //数据库判断院方系统编码重复
        List<PatientCaseInfo> nameList = patientCaseInfoMapper.listByZhuYuanHao(zhuyuanhaoMapGroup.keySet());
        if (CollUtil.isNotEmpty(nameList)) {
            List<PatientCaseInfo> finalNameList = nameList;
            List<String> checkNames = new ArrayList<>();
            patientCaseList.forEach(respVOZhuyuanhao -> {
                Optional<PatientCaseInfo> productOpt = finalNameList.stream().filter(name -> respVOZhuyuanhao.getZhuyuanhao().equals(name.getZhuyuanhao())).findFirst();
                if (productOpt.isPresent()) {
                    checkNames.add(respVOZhuyuanhao.getZhuyuanhao());

                }
            });

            if (CollUtil.isNotEmpty(checkNames)) {
                String message = StrUtil.join("，", checkNames);
                throw new ServiceException("住院号已重复：" + message + "已经存在病案信息管理系统!");
            }
        }


        //把问题id转为key
        Map<String, Surgery> surgeryMap = surgeryService.listByName(surgeryNameList)
                .stream().collect(Collectors.toMap(Surgery::getName, item -> item, (key1, key2) -> key2));

        //把问题id转为key
        Map<String, Diagnose> diagnoseMap = diagnoseService.listByName(diagnoseNameList)
                .stream().collect(Collectors.toMap(Diagnose::getName, item -> item, (key1, key2) -> key2));


        patientCaseList.forEach(item -> {
            if (surgeryMap.containsKey(item.getShoushucaozuomingcheng())) {
                item.setShoushucaozuobianma(surgeryMap.get(item.getShoushucaozuomingcheng()).getCode());
            }
            if (diagnoseMap.containsKey(item.getRuyuanzhenduan())) {
                item.setRuyuanzhenduanbianma(diagnoseMap.get(item.getRuyuanzhenduan()).getCode());
            }
            if (diagnoseMap.containsKey(item.getChuyuanzhuzhenduan())) {
                item.setChuyuanzhuzhenduanbianma(diagnoseMap.get(item.getChuyuanzhuzhenduan()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan1())) {
                item.setCizhenduan1bianma(diagnoseMap.get(item.getCizhenduan1()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan2())) {
                item.setCizhenduan2bianma(diagnoseMap.get(item.getCizhenduan2()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan3())) {
                item.setCizhenduan3bianma(diagnoseMap.get(item.getCizhenduan3()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan4())) {
                item.setCizhenduan4bianma(diagnoseMap.get(item.getCizhenduan4()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan5())) {
                item.setCizhenduan5bianma(diagnoseMap.get(item.getCizhenduan5()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan6())) {
                item.setCizhenduan6bianma(diagnoseMap.get(item.getCizhenduan6()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan7())) {
                item.setCizhenduan7bianma(diagnoseMap.get(item.getCizhenduan7()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan8())) {
                item.setCizhenduan8bianma(diagnoseMap.get(item.getCizhenduan8()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan9())) {
                item.setCizhenduan9bianma(diagnoseMap.get(item.getCizhenduan9()).getCode());
            }
            if (diagnoseMap.containsKey(item.getCizhenduan10())) {
                item.setCizhenduan10bianma(diagnoseMap.get(item.getCizhenduan10()).getCode());
            }
        });

        this.buildData(patientCaseList, true);
        patientCaseInfoMapper.saveBatch(patientCaseList);
        return "导入成功";
    }

    public void addName(List<String> diagnoseNameList, String name) {
        if (StrUtil.isNotBlank(name)) {
            diagnoseNameList.add(name);
        }
    }

    @Override
    public List<PatientCaseRespVO> print(Long[] ids) {
        if (ids == null || ids.length == 0) {
            return CollUtil.newArrayList();
        }

        List<PatientCaseRespVO> list = patientCaseInfoMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list)) {
            return CollUtil.newArrayList();
        }
        //由于打印机不支持  连续打印两份相同的  这里循环处理
        List<PatientCaseRespVO> respVOList = new ArrayList<>();
        list.forEach(item -> {
            respVOList.add(item);
            respVOList.add(item);
        });
        return respVOList;
    }


    @Override
    public int audit(Long[] ids) {
        return patientCaseInfoMapper.audit(ids);
    }

    @Override
    public int repeal(Long[] ids) {
        return patientCaseInfoMapper.repeal(ids);
    }

    @Override
    public List<PatientCaseInfo> export(Long[] ids) {
        return patientCaseInfoMapper.listByIds(ids);
    }
}
